import random
# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="Pieman"
__date__ ="$20/11/2010 2:51:57 PM$"

class Terrain:
    def __init__(self, name):
        #name of the actual terrain type, like room, corridor, grass, etc
        self.name = name
        #variant or positional specific details, eg. 1, 2, 'left-right', 'top-left', etc
        self.context = "0"
        self.block_light = 1
        self.block_sound = 1
        self.block_path = 1
        self.block_roof = 1
        self.move_penalty = 10

        #will affect light in the tile as a modifier
        self.ambient_light = 0
        #will affect sound in the tile as a modifier
        self.acoustics = 0

class Tile:
    def __init__(self, x, y):
        #position within the level
        self.x = x
        self.y = y
        #affects fog of war and player view
        self.visible = 'none'
        self.terrain = Terrain('none')
        self.occupant = None
        self.doodad = None
        self.items = []

    def set_occupant(self, occ):
        self.occupant = occ
        occ.x, occ.y = self.x, self.y

    def add_item(self, itm):
        self.items.append(itm)
        itm.x, itm.y = self.x, self.y

    def is_blocked(self, name):
        if name == 'light':
            return self.is_light_blocked()
        elif name == 'sound':
            return self.is_sound_blocked()
        elif name == 'path':
            return self.is_path_blocked()
        elif name == 'roof':
            return self.is_roof_blocked()
        else:
            return 1

    def is_light_blocked(self):
        res = 0
        if self.doodad is not None:
            res = self.doodad.state.block_light
        return self.terrain.block_light + res

    def is_sound_blocked(self):
        res = 0
        if self.doodad is not None:
            res = self.doodad.state.block_sound
        return self.terrain.block_sound + res

    def is_path_blocked(self):
        res = 0
        if self.doodad is not None:
            res = self.doodad.state.block_path
        return self.terrain.block_path + res

    def is_roof_blocked(self):
        res = 0
        if self.doodad is not None:
            res = self.doodad.state.block_roof
        return self.terrain.block_roof + res

    def is_diag_blocked(self):
        if self.doodad is None:
            return 0
        else:
            return self.doodad.state.allow_diag == 0

class Room:
    def __init__(self, x, y, w, h):
        self.x = x
        self.y = y
        self.w = w
        self.h = h

        self.xw = x + w
        self.yh = y + h

        if self.w < 0:
            print x, y, w, h

        if self.h < 0:
            print x, y, w, h

        self.left = None
        self.right = None

    #get a random horizontal position of the room
    #the absolute sides of the room are not included
    #min and max are values between 0-100 as a percentage range the value will be
    def random_x(self, min=0.0, max=100.0):
        leftmost = self.x + 1
        rightmost = self.xw - 1

#        print "preleftmost: {0}, prerightmost: {1} and min/max are {2}, {3}, self is {4}, {5}".format(leftmost, rightmost, min, max, self.x, self.xw)
#        la = int((self.w - 2) * (min / 100))
#        print "left adjust: {0}".format(la)
        leftmost += int((self.w - 2) * (min / 100))
        rightmost -= int((self.w - 2) * ((100 - max) / 100))
#        print "postleftmost: {0}, postrightmost: {1} ".format(leftmost, rightmost)
#        if leftmost > rightmost:
#            print self.x, self.xw, self.w
#        if leftmost < rightmost:
#            raise Error('Not cool')
        return random.randint(leftmost, rightmost)

    def random_y(self, min=0.0, max=100.0):
        topmost = self.y + 1
        bottommost = self.yh - 1

        topmost += int((self.h - 2) * (min / 100))
        bottommost -= int((self.h - 2) * ((100 - max) / 100))
       # print topmost, bottommost, self.y, self.yh
#        if topmost > bottommost:
#            print self.y, self.yh, self.h
#        if topmost < bottommost:
#            raise Error('Not Awesome')
        return random.randint(topmost, bottommost)

    def random_pos(self):
        return [self.random_x(), self.random_y()]

    def leaf(self):
        return self.left is None and self.right is None


class Level:
    def __init__(self, width, height, theme, sprite_pitch):
        self.width = width
        self.height = height
        self.theme = theme
        #self.dlevel = dlvl
        self.sprite_pitch = sprite_pitch

        self.tiles = []
        for i in xrange(width):
            tt = []
            for j in xrange(height):
                tt.append(Tile(i, j))
            self.tiles.append(tt)
        self.rooms = None
        self.background = None

        self.tileset = {}

    def set_lit(self, x, y, id):
        self.tiles[x][y].visible = 'full'
        
    def apply_fog(self):
        for i in range(self.width):
            for j in range(self.height):
                if self.tiles[i][j].visible == 'full':
                    self.tiles[i][j].visible = 'fog'

    def unplace_all_chars(self):
        for i in range(width):
            for j in range(height):
                self.tiles[i][j].occupant = None

    def random_tile(self, **args):
        room = self.rooms
        while not room.leaf():
            r = random.randint(0, 1)
            if r == 1: room = room.left
            else: room = room.right

        x, y = room.random_x(), room.random_y()
        if 'item' in args:
            if (args['item'] == 'none' and len(self.tiles[x][y].items) > 0) or \
                (args['item'] == 'one' and len(self.tiles[x][y].item) != 1) or \
                (args['item'] == 'multi' and len(self.tiles[x][y].item) < 2):
                return self.random_tile(**args)

        if 'occupant' in args:
            if (args['occupant'] == 'none' and self.tiles[x][y].occupant is not None) or \
                (args['occupant'] == 'occupied' and self.tiles[x][y].occupant is None):
                return self.random_tile(**args)
        return self.tiles[x][y]
        


#    def place_random_char(self, obj):
#        px, py = self.rooms[random.randint(0, len(self.rooms) - 1)].random_pos()
#        while self.tiles[px][py].occupant != None:
#            px, py = self.rooms[random.randint(0, len(self.rooms) - 1)].random_pos()
#        self.tiles[px][py].occupant = obj
#        obj.x, obj.y = [px, py]
#        obj.rect.topleft = (px * self.sprite_pitch[0], py * self.sprite_pitch[1])
#        return [px, py]
#
#    def place_random_item(self, itm):
#        px, py = self.rooms[random.randint(0, len(self.rooms) - 1)].random_pos()
#        self.tiles[px][py].items.append(itm)
#        itm.x, itm.y = [px, py]
#        itm.rect.topleft = (px * self.sprite_pitch[0], py * self.sprite_pitch[1])
#        return [px, py]

    def open_door(self, x, y):
        t = self.tiles[x][y]
        if t.context != 'door_closed':
            return None
        t.context = 'door_open'
        t.collision = 'empty'
        self.reblit_background(x, y)
        return None

    def close_door(self, x, y):
        t = self.tiles[x][y]
        if t.context != 'door_open':
            return None
        t.context = 'door_closed'
        t.collision = 'solid'
        self.reblit_background(x, y)
        return None

    def pickup(self, src, dst):
        picker = self.tiles[src[0]][src[1]].occupant
        if picker == None:
            return None

        nx = src[0] + dst[0]
        ny = src[1] + dst[1]

        itms = self.tiles[nx][ny].items
        s = len(itms)

        if s == 0:
            return None

        picker.add_inventory(itms)
        self.tiles[nx][ny].items = []

        return itms

    def check(self, src, dst):
        checker = self.tiles[src[0]][src[1]].occupant
        if checker == None:
            return None

        nx = src[0] + dst[0]
        ny = src[1] + dst[1]

        itms = self.tiles[nx][ny].items
        s = len(itms)
        if s == 0:
            return None
        return itms


    def create_background(self, back):
        self.background = back
        x = 0
        for tx in self.tiles:
            y = 0
            for ty in tx:
                bt = self.tileset[ty.terrain.name][ty.terrain.context]
                self.background.blit(bt, (x * self.sprite_pitch[0], y * self.sprite_pitch[1]))

                if ty.doodad is not None:
                    dt = self.tileset[ty.doodad.name][ty.doodad.state.name]
                    self.background.blit(dt, (x * self.sprite_pitch[0], y * self.sprite_pitch[1]))
                y = y + 1
            #end for
            x = x + 1

    def reblit_background(self, x, y):
        t = self.tiles[x][y]
        bt = self.tileset[t.terrain.name][t.terrain.context]
        self.background.blit(bt, (x * self.sprite_pitch[0], y * self.sprite_pitch[1]))
        if t.doodad is not None:
            dt = self.tileset[t.doodad.name][t.doodad.state.name]
            self.background.blit(dt, (x * self.sprite_pitch[0], y * self.sprite_pitch[1]))


